
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Random;

import org.jmusixmatch.MusixMatch;
import org.jmusixmatch.MusixMatchException;
import org.jmusixmatch.entity.lyrics.Lyrics;
import org.jmusixmatch.entity.track.Track;
import org.jmusixmatch.entity.track.TrackData;


import com.modestmaps.InteractiveMap;
import com.modestmaps.geo.Location;
import com.modestmaps.providers.Microsoft;

import processing.core.*;

public class Main extends PApplet {

	// Db driver
	public static final String driver = "org.sqlite.JDBC";
	
	Button infoButton;
	PImage infoImage;

	public void setup() {
		size(GLOBAL.width,GLOBAL.height);

		GLOBAL.processing=this;
		GLOBAL.gu = new GradientUtils();

		setupColor();

		Parser pars = new Parser();

		// hack to report mouse wheel events
		addMouseWheelListener(new java.awt.event.MouseWheelListener() { 
			public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { 
				mouseWheel(evt.getWheelRotation());
			}
		}
				);

		GLOBAL.plotBoldFont = createFont("MicrosoftTaiLe-Bold",20);
		GLOBAL.plotFont = createFont("MicrosoftTaiLe", 20);
		GLOBAL.newFont = createFont("TwCenMT-BoldItalic",20);

		background(0);

		setupDatabaseConnection();

		// Setup screen areas
		GLOBAL.selectionPanel = new SelectionPanel();
		GLOBAL.selectionPanel.x=0; GLOBAL.selectionPanel.y=0;
		GLOBAL.selectionPanel.width=1024; GLOBAL.selectionPanel.height=70;
		GLOBAL.infoPanel = new InfoPanel();
		GLOBAL.infoPanel.x=GLOBAL.width-250; GLOBAL.infoPanel.y=70;
		GLOBAL.infoPanel.width=250; GLOBAL.infoPanel.height=GLOBAL.height-GLOBAL.infoPanel.y;

		GLOBAL.multistatePanel = new MultistatePanel(315,height-45, 400,40);
		GLOBAL.mapArea = new MapArea(0, GLOBAL.selectionPanel.height,
				width, height - GLOBAL.selectionPanel.height);
		GLOBAL.chartsArea = new ChartsArea(0, GLOBAL.selectionPanel.height,
				width, height - GLOBAL.selectionPanel.height);

		// Download top artists
		Artist.downloadLastfmTopArtists();

		// create a new map, optionally specify a provider
		GLOBAL.mapClass = new Map();
		GLOBAL.mapClass.map = new InteractiveMap(this,   new Microsoft.HybridProvider());

		// set the initial location and zoom level to Chicago:
		GLOBAL.mapClass.map.setCenterZoom(new Location((float)(45.881944), (float)(11.627778)), 5);
		// zoom 0 is the whole world, 19 is street level
		// (try some out, or use getlatlon.com to search for more)

		// set a default font for labels
		GLOBAL.mapClass.font = createFont("Helvetica", 12);
		GLOBAL.mapClass.map.MAX_IMAGES_TO_KEEP=80;
		GLOBAL.mapClass.map.sc=5;

		// enable the mouse wheel, for zooming
		addMouseWheelListener(new java.awt.event.MouseWheelListener() { 
			public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { 
				mouseWheel(evt.getWheelRotation());
			}
		}
				); 

		frameRate(17);

		smooth();

		// Create Network Graph
		GLOBAL.graphsArea = new GraphsArea(0,GLOBAL.selectionPanel.height,
				width - GLOBAL.infoPanel.width, height - GLOBAL.selectionPanel.height);

		// Songs analysis tab
		GLOBAL.songsArea = new SongsArea(0, GLOBAL.selectionPanel.height, 
				width, height - GLOBAL.selectionPanel.height);
		
		infoButton = new Button("Info", 20, GLOBAL.height - 35);
		infoImage = loadImage("info.png");

	}

	public void draw() {
		background(GLOBAL.colorBackground);
		// calulcate dTime
		int t = millis();
		float dt = (float) (t - GLOBAL.timer) / (float)1000.0;
		GLOBAL.timer = t;

		if (GLOBAL.analysisType == 0) {
			GLOBAL.chartsArea.draw();
		}
		// Map draw
		else if (GLOBAL.analysisType == 1) {
			GLOBAL.mapClass.draw(dt);
			GLOBAL.mapArea.draw();
		}
		else if (GLOBAL.analysisType == 2){
			GLOBAL.graphsArea.networkGraph.draw();
		}
		else if (GLOBAL.analysisType == 3){
			GLOBAL.songsArea.draw();
		}

		// Draw screen areas
		if(GLOBAL.analysisType == 2)
			GLOBAL.selectionPanel.textBoxArtist.draw();
		GLOBAL.infoPanel.draw();
		GLOBAL.selectionPanel.draw();
		GLOBAL.multistatePanel.draw();

		if (GLOBAL.analysisType == 2 ||
				GLOBAL.analysisType == 3) {
			GLOBAL.processing.rectMode(GLOBAL.processing.CORNER);
			GLOBAL.processing.fill(GLOBAL.processing.color(40,40,40,150));
			GLOBAL.processing.rect(0, 0, GLOBAL.width, GLOBAL.selectionPanel.height);
		}

		infoButton.draw();
		
		if (GLOBAL.show_info && infoImage!= null)
			drawInfoImage();
		
		

	}

	public void drawInfoImage() {
		stroke(color(80,80,80,200));
		strokeWeight(2);
		rectMode(CORNER);
		rect(299,199,infoImage.width+1,infoImage.height+1);
		image(infoImage, 300, 200);

	}
	
	public void setupColor() {
		//init colors
		GLOBAL.colors = new int[4];		
		GLOBAL.colors[0]= color(51,34,136); 
		GLOBAL.colors[1]= color(68,170,153);
		GLOBAL.colors[2]= color(221,204,119); 
		GLOBAL.colors[3]= color(136,34,85);
		GLOBAL.menuColor = color(28,28,28,200);

		// COLOR SWATCH 
		int[] temp = {color(136,204,238), color(17,119,51), color(221,204,119), 
				color(204,102,119), color(146,189,16), color(170,68,153), 
				color(115,100,190)//, color(200,200,200)68,170,153
		};

		//Randomize colors
		int[] c = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
		Random rand = new Random();

		for(int x=0; x<temp.length; ++x){
			int n = rand.nextInt(temp.length);
			while(c[n] != -1) {
				n = rand.nextInt(temp.length);
			}
			c[n] = temp[x];
		}

		GLOBAL.COLORS = new ColorSwatch(c);
		// END 
	}

	void mouseWheel(int d) {
		if(GLOBAL.analysisType == 1 && !GLOBAL.selectionPanel.mouseOver()){
			GLOBAL.mapClass.mouseWheel(d);
		}

	}

	public void mouseDragged() {

		// Update mouse x value
		if(GLOBAL.analysisType == 0 && GLOBAL.chartsArea.mouseOver()) {
			GLOBAL.chartsArea.mouseDragged();
		}

		if(GLOBAL.analysisType == 2 && GLOBAL.graphsArea.mouseOver())GLOBAL.graphsArea.networkGraph.mouseDragged();
		if(GLOBAL.analysisType == 1 && !GLOBAL.selectionPanel.mouseOver()){
			if(!GLOBAL.selectionPanel.textBoxNationality.active || ( !GLOBAL.selectionPanel.textBoxNationality.mouseOver()
					&& !GLOBAL.selectionPanel.textBoxNationality.mouseOverSuggestions()
					&& !GLOBAL.selectionPanel.textBoxNationality.scrollBar.mouseOver()))
				if(!GLOBAL.selectionPanel.textBoxArtist.active ||( !GLOBAL.selectionPanel.textBoxArtist.mouseOver()
						&& !GLOBAL.selectionPanel.textBoxArtist.mouseOverSuggestions()
						&& !GLOBAL.selectionPanel.textBoxArtist.scrollBar.mouseOver()))
					if(GLOBAL.selectionPanel.nationalities.pluState || (!GLOBAL.selectionPanel.nationalitiesScrollBar.mouseOver())){
						GLOBAL.mapClass.mouseDragged();
					}
		}
	}

	public void mouseClicked() {
		if(GLOBAL.analysisType == 1 && !GLOBAL.selectionPanel.mouseOver())
			GLOBAL.mapClass.mouseClicked();
	}

	public void keyTyped(){
		if(GLOBAL.selectionPanel.textBoxArtist.active)GLOBAL.selectionPanel.textBoxArtist.keyTyped();
		if(GLOBAL.selectionPanel.textBoxNationality.active)GLOBAL.selectionPanel.textBoxNationality.keyTyped();
		if(GLOBAL.songsArea.textBoxSong.active)GLOBAL.songsArea.textBoxSong.keyTyped();
	}

	public void keyReleased() {
		if(GLOBAL.analysisType == 1)
			GLOBAL.mapClass.keyReleased();
	}

	public void mousePressed(){
		// else textbox artist
		if((GLOBAL.analysisType == 2) && 
				GLOBAL.selectionPanel.textBoxArtist.scrollBar.mouseOver())
			GLOBAL.selectionPanel.textBoxArtist.scrollBar.mousePressed();
		else if((GLOBAL.analysisType == 2) &&
				GLOBAL.selectionPanel.textBoxArtist.mouseOver()){
			if(!GLOBAL.selectionPanel.textBoxArtist.active){GLOBAL.selectionPanel.textBoxArtist.active=true;}
			else{GLOBAL.selectionPanel.textBoxArtist.active=false;}
		}		
		else if((GLOBAL.analysisType == 0 || GLOBAL.analysisType == 1) &&
				GLOBAL.selectionPanel.textBoxNationality.active 
				&& GLOBAL.selectionPanel.textBoxNationality.mouseOverSuggestions())GLOBAL.selectionPanel.textBoxNationality.mousePressed();
		else if((GLOBAL.analysisType == 3) &&
				GLOBAL.songsArea.textBoxSong.active 
				&& GLOBAL.songsArea.textBoxSong.mouseOverSuggestions())GLOBAL.songsArea.textBoxSong.mousePressed();

		if ((GLOBAL.analysisType == 0 || GLOBAL.analysisType == 1) &&
				!GLOBAL.selectionPanel.nationalities.pluState) {
			for (int i=0;i<GLOBAL.nationalitiesButtonSelected.size();i++){
				if(GLOBAL.nationalitiesButtonSelected.get(i).active){
					if(GLOBAL.nationalitiesButtonSelected.get(i).mouseOver())
						GLOBAL.nationalitiesButtonSelected.get(i).mouseCliked();
				}
			}
			if(GLOBAL.selectionPanel.nationalitiesScrollBar.mouseOver())
				GLOBAL.selectionPanel.nationalitiesScrollBar.mousePressed();
		}


		if((GLOBAL.analysisType == 0 || GLOBAL.analysisType == 1 || GLOBAL.analysisType == 2) &&
				GLOBAL.selectionPanel.mouseOver()) {	
			GLOBAL.selectionPanel.mousePressed();
		}
		else if(GLOBAL.analysisType == 2 && GLOBAL.infoPanel.mouseOver()) {
			GLOBAL.infoPanel.mousePressed();
		}
		else if(GLOBAL.multistatePanel.mouseOver()) {
			GLOBAL.multistatePanel.mousePressed();
		}
		else if(GLOBAL.mapArea.mouseOver() && GLOBAL.analysisType == 1) {
			GLOBAL.mapArea.mousePressed();		
		}
		else if(GLOBAL.analysisType == 0 && GLOBAL.chartsArea.mouseOver()) {
			GLOBAL.chartsArea.mousePressed();
		}
		else if (GLOBAL.analysisType == 2 && GLOBAL.graphsArea.mouseOver()) {
			GLOBAL.graphsArea.networkGraph.mousePressed();
		}	
		else if (GLOBAL.analysisType == 3 && GLOBAL.songsArea.mouseOver()) {
			GLOBAL.songsArea.mousePressed();
		}
		
		if (infoButton.mouseOver()) {
			GLOBAL.show_info = !GLOBAL.show_info;
			infoButton.state = GLOBAL.show_info;
		}

	}

	public void mouseReleased(){
		GLOBAL.selectionPanel.mouseReleased();
		GLOBAL.infoPanel.mouseReleased();
		if(GLOBAL.analysisType == 0)
			GLOBAL.chartsArea.mouseReleased();
		else if (GLOBAL.analysisType == 2){
			GLOBAL.graphsArea.networkGraph.mouseReleased();
		}
		else if (GLOBAL.analysisType == 3){
			GLOBAL.songsArea.mouseReleased();
		}

	}

	public static void main(String [] args){
		PApplet.main(new String[] { "--present --location=0,0", "Main" });
	}

	public void setupDatabaseConnection() {
		//STEP 1: Setup the Driver
		try
		{
			//Load the JDBC driver class dynamically.
			Driver d = (Driver)Class.forName(driver).newInstance();
			DriverManager.registerDriver(d);
		}
		catch(Exception e)
		{
			System.out.println("Error loading database driver: " + e.toString());
			return;
		}

		//STEP 2: Create connection to database using database URL
		try
		{
			String url = "jdbc:sqlite:data/lastfm.db";
			GLOBAL.user_db_con = DriverManager.getConnection(url);
			String url2 = "jdbc:sqlite:data/times.db";
			GLOBAL.user_times_con = DriverManager.getConnection(url2);
			System.out.println("DB Connection OK");
		}
		catch(SQLException e)
		{
			System.out.println("Error creating connection: " + e.toString());
			e.printStackTrace();
			return;
		}

		// Test a select

		/*

        //STEP 3: Execute SQL query using Statement object
        Statement stmt;
        ResultSet res;
        try
        {
        	String sql = "SELECT T.user_code, T.date, T.plays from usersTime as U INNER JOIN times as T on U.user_code == T.user_code where U.nationality =='United States';";
        	stmt = GLOBAL.user_times_con.createStatement();
        	res = stmt.executeQuery(sql);
        }
        catch(SQLException e)
        {
        	System.out.println("Error creating or running statement: " + e.toString());
        	try
        	{
        		GLOBAL.user_db_con.close();
        	}
        	catch(Exception e2)
        	{
        	}
        	return;
        }

        //STEP 4: Read results
        try
        {
        	int user_code;
        	int plays;
        	while(res.next())
        	{
        		user_code = res.getInt("user_code");
        		plays = res.getInt("plays");
        		System.out.println("-> "+ user_code +" "+plays );
        	}
        }
        catch(Exception e)
        {
        	System.out.println("Error processing results: " + e.toString());
        	try
        	{
        		res.close();
        		stmt.close();
        		GLOBAL.user_db_con.close();
        	}
        	catch(Exception ex)
        	{
        	}
        	return;
        }

		 */
	}

	//	public void setupTwitterConnection(){
	//		ConfigurationBuilder cb = new ConfigurationBuilder();
	//		cb.setOAuthConsumerKey("frFZcmeCkqclKkfbS7u8A");
	//		cb.setOAuthConsumerSecret("YXzRnQ2ULSi8WkVfy0dF3YNghm8VqNa2Yt7lkZvKh4");
	//		cb.setOAuthAccessToken("411848822-XTIZ1OGOH1bEV0DrLaETVtXoB64nvYh6Th7JreST");
	//		cb.setOAuthAccessTokenSecret("PVc7VT2ob6EfQrNaVzc25Sjt77sCnU1vCj7xT3QTRs");
	//		
	//		Twitter twitter = new TwitterFactory(cb.build()).getInstance();
	//		
	//		Query query = new Query("#Madonna");
	//		query.setRpp(100);
	//		 
	//		try {
	//		  QueryResult result = twitter.search(query);
	//		  ArrayList tweets = (ArrayList) result.getTweets();
	//		 
	//		  for (int i = 0; i < tweets.size(); i++) {
	//		    Tweet t = (Tweet) tweets.get(i);
	//		    String user = t.getFromUser();
	//		    String msg = t.getText();
	//		    Date d = t.getCreatedAt();
	//		    println("Tweet by " + user + " at " + d + ": " + msg);
	//		  };
	//		}
	//		catch (TwitterException te) {
	//		  println("Couldn't connect: " + te);
	//		};
	//	}

//	// TEST FUNCTION
//	private void tryLyrics() {
//
//		String apiKey = "71dd2cc2de9e53d13ac03c9d783a7aa3";
//		MusixMatch musixMatch = new MusixMatch(apiKey);
//
//		String trackName;
//		String artistName;
//		String l = "";
//
//
//		// Track Search [ Fuzzy ]
//		Track track;
//		try {
//
//
//			TrackData data;
//			Lyrics lyrics;
//
//			trackName = "Viva la vida";
//			artistName = "Coldplay";
//			track = musixMatch.getMatchingTrack(trackName, artistName);
//
//			data = track.getTrack();
//
//			System.out.println("AlbumID : "    + data.getAlbumId());
//			System.out.println("Album Name : " + data.getAlbumName());
//			System.out.println("Artist ID : "  + data.getArtistId());
//			System.out.println("Album Name : " + data.getArtistName());
//			System.out.println("Track ID : "   + data.getTrackId());
//
//			int trackID = data.getTrackId();
//
//			lyrics = musixMatch.getLyrics(trackID);
//
//			l = lyrics.getLyricsBody();
//
//			trackName = "Man in the mirror";
//			artistName = "Michael Jackson";
//			track = musixMatch.getMatchingTrack(trackName, artistName);
//
//			data = track.getTrack();
//
//			System.out.println("AlbumID : "    + data.getAlbumId());
//			System.out.println("Album Name : " + data.getAlbumName());
//			System.out.println("Artist ID : "  + data.getArtistId());
//			System.out.println("Album Name : " + data.getArtistName());
//			System.out.println("Track ID : "   + data.getTrackId());
//
//			trackID = data.getTrackId();
//
//			lyrics = musixMatch.getLyrics(trackID);
//
//			l = l + " "+ lyrics.getLyricsBody();
//
//			//System.out.println("Lyrics Body     : "     + lyrics.getLyricsBody());
//
//			GLOBAL.songsArea.changeTagCloud(l);
//
//
//		} catch (MusixMatchException e) {
//			System.err.println("MusixMatch lyrics download error");
//			e.printStackTrace();
//		}
//
//	}

}

